﻿using DKPScoreWebApi.Data;
using DKPScoreWebApi.DTOs.Requests;
using DKPScoreWebApi.DTOs.Results;
using DKPScoreWebApi.Models;
using DKPScoreWebApi.Services.Interfaces;
using Microsoft.EntityFrameworkCore;

namespace DKPScoreWebApi.Services.Implementations
{
    public class DkpService : IDkpService
    {
        private readonly AppDbContext _context;
        private readonly ILogger<DkpService> _logger;

        public DkpService(AppDbContext context, ILogger<DkpService> logger)
        {
            _context = context;
            _logger = logger;
        }

        public async Task<PointResult> AddPointsAsync(int userId, int guildId, AddPointsRequest request)
        {
            var member = await _context.GuildMembers
                .FirstOrDefaultAsync(m => m.Id == request.MemberId && m.GuildId == guildId && m.IsActive);
            var item = await _context.PointItems
                .FirstOrDefaultAsync(i => i.Id == request.ItemId && i.GuildId == guildId && i.IsActive);

            if (member == null || item == null)
                return new PointResult { Success = false, Message = "成员或项目不存在" };

            int points = item.PointType switch
            {
                "add" => item.BasePoints,
                "subtract" => -item.BasePoints,
                _ => 0
            };

            if (points == 0)
                return new PointResult { Success = false, Message = "此项目不支持直接加减分" };

            var record = new PointRecord
            {
                GuildId = guildId,
                MemberId = request.MemberId,
                ItemId = request.ItemId,
                PointsEarned = points,
                Description = request.Description ?? $"完成{item.Name}",
                RaidName = request.RaidName,
                RaidDate = request.RaidDate,
                CreatedBy = userId,
                CreatedAt = DateTime.Now
            };

            _context.PointRecords.Add(record);
            await _context.SaveChangesAsync();

            // 计算成员当前总积分
            var totalPoints = await GetMemberTotalPointsAsync(request.MemberId);

            _logger.LogInformation("用户 {UserId} 为成员 {MemberName} {Operation} {Points} DKP",
                userId, member.Name, points > 0 ? "增加" : "减少", Math.Abs(points));

            return new PointResult
            {
                Success = true,
                PointsEarned = points,
                TotalPoints = totalPoints
            };
        }

        public async Task<ProgressResult> UpdateProgressAsync(int userId, int guildId, UpdateProgressRequest request)
        {
            var member = await _context.GuildMembers
                .FirstOrDefaultAsync(m => m.Id == request.MemberId && m.GuildId == guildId && m.IsActive);
            var item = await _context.PointItems
                .FirstOrDefaultAsync(i => i.Id == request.ItemId && i.GuildId == guildId && i.IsActive);

            if (member == null || item == null || item.PointType != "progress")
                return new ProgressResult { Success = false, Message = "成员或项目不存在，或项目类型错误" };

            // 获取或创建成员进度
            var memberProgress = await _context.MemberProgresses
                .FirstOrDefaultAsync(mp => mp.MemberId == request.MemberId && mp.ItemId == request.ItemId);

            if (memberProgress == null)
            {
                memberProgress = new MemberProgress
                {
                    MemberId = request.MemberId,
                    ItemId = request.ItemId,
                    CurrentProgress = 0,
                    LastUpdated = DateTime.Now
                };
                _context.MemberProgresses.Add(memberProgress);
            }

            memberProgress.CurrentProgress += request.ProgressIncrement;
            memberProgress.LastUpdated = DateTime.Now;

            int pointsEarned = 0;
            // 检查是否达到目标进度
            if (memberProgress.CurrentProgress >= item.TargetProgress && item.TargetProgress > 0)
            {
                pointsEarned = item.BasePoints;
                int cycles = memberProgress.CurrentProgress / item.TargetProgress;
                memberProgress.CurrentProgress %= item.TargetProgress; // 保留剩余进度

                // 创建积分记录
                var record = new PointRecord
                {
                    GuildId = guildId,
                    MemberId = request.MemberId,
                    ItemId = request.ItemId,
                    PointsEarned = pointsEarned,
                    ProgressValue = request.ProgressIncrement,
                    Description = $"完成{item.Name}进度目标",
                    CreatedBy = userId,
                    CreatedAt = DateTime.Now
                };

                _context.PointRecords.Add(record);
            }

            await _context.SaveChangesAsync();

            // 计算成员当前总积分
            var totalPoints = await GetMemberTotalPointsAsync(request.MemberId);

            _logger.LogInformation("用户 {UserId} 更新成员 {MemberName} 进度 {ItemName}: +{Progress}",
                userId, member.Name, item.Name, request.ProgressIncrement);

            return new ProgressResult
            {
                Success = true,
                CurrentProgress = memberProgress.CurrentProgress,
                PointsEarned = pointsEarned,
                TotalPoints = totalPoints,
                IsTargetReached = pointsEarned > 0
            };
        }

        public async Task<List<PointRecord>> GetMemberRecordsAsync(int guildId, int memberId, DateTime? startDate = null, DateTime? endDate = null)
        {
            var query = _context.PointRecords
                .Where(pr => pr.GuildId == guildId && pr.MemberId == memberId)
                .Include(pr => pr.PointItem)
                .Include(pr => pr.Creator);

            if (startDate.HasValue)
                query = (Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<PointRecord, WxUser>)query.Where(pr => pr.CreatedAt >= startDate.Value);
            if (endDate.HasValue)
                query = (Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<PointRecord, WxUser>)query.Where(pr => pr.CreatedAt <= endDate.Value);

            return await query
                .OrderByDescending(pr => pr.CreatedAt)
                .ToListAsync();
        }

        public async Task<List<GuildMember>> GetGuildRankingAsync(int guildId, int topCount = 50)
        {
            var members = await _context.GuildMembers
                .Where(m => m.GuildId == guildId && m.IsActive)
                .ToListAsync();

            // 计算每个成员的总积分
            var memberPoints = new Dictionary<int, int>();
            foreach (var member in members)
            {
                memberPoints[member.Id] = await GetMemberTotalPointsAsync(member.Id);
            }

            return members
                .OrderByDescending(m => memberPoints[m.Id])
                .Take(topCount)
                .Select(m =>
                {
                    m.TotalPoints = memberPoints[m.Id];
                    return m;
                })
                .ToList();
        }

        public async Task<List<PointItem>> GetGuildPointItemsAsync(int guildId)
        {
            return await _context.PointItems
                .Where(pi => pi.GuildId == guildId && pi.IsActive)
                .OrderBy(pi => pi.PointType)
                .ThenBy(pi => pi.Name)
                .ToListAsync();
        }

        public async Task<PointItem> CreatePointItemAsync(int guildId, CreateItemRequest request)
        {
            var item = new PointItem
            {
                GuildId = guildId,
                Name = request.Name,
                Description = request.Description,
                PointType = request.PointType,
                BasePoints = request.BasePoints,
                TargetProgress = request.TargetProgress,
                CreatedAt = DateTime.Now
            };

            _context.PointItems.Add(item);
            await _context.SaveChangesAsync();

            _logger.LogInformation("创建积分项目 {ItemName} 于工会 {GuildId}", request.Name, guildId);
            return item;
        }

        public async Task<bool> UpdatePointItemAsync(int itemId, CreateItemRequest request)
        {
            var item = await _context.PointItems.FindAsync(itemId);
            if (item == null)
                return false;

            item.Name = request.Name;
            item.Description = request.Description;
            item.PointType = request.PointType;
            item.BasePoints = request.BasePoints;
            item.TargetProgress = request.TargetProgress;

            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> DeletePointItemAsync(int itemId)
        {
            var item = await _context.PointItems.FindAsync(itemId);
            if (item == null)
                return false;

            item.IsActive = false;
            await _context.SaveChangesAsync();

            return true;
        }

        public async Task<PointItem> GetPointItemByIdAsync(int itemId)
        {
            return await _context.PointItems
                .Include(pi => pi.Guild)
                .FirstOrDefaultAsync(pi => pi.Id == itemId);
        }

        public async Task<List<PointRecord>> GetGuildRecordsAsync(int guildId, DateTime? startDate = null, DateTime? endDate = null, int? memberId = null)
        {
            var query = _context.PointRecords
                .Where(pr => pr.GuildId == guildId)
                .Include(pr => pr.Member)
                .Include(pr => pr.PointItem)
                .Include(pr => pr.Creator);

            if (startDate.HasValue)
                query = (Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<PointRecord, WxUser>)query.Where(pr => pr.CreatedAt >= startDate.Value);
            if (endDate.HasValue)
                query = (Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<PointRecord, WxUser>)query.Where(pr => pr.CreatedAt <= endDate.Value);
            if (memberId.HasValue)
                query = (Microsoft.EntityFrameworkCore.Query.IIncludableQueryable<PointRecord, WxUser>)query.Where(pr => pr.MemberId == memberId.Value);

            return await query
                .OrderByDescending(pr => pr.CreatedAt)
                .ToListAsync();
        }

        private async Task<int> GetMemberTotalPointsAsync(int memberId)
        {
            return await _context.PointRecords
                .Where(pr => pr.MemberId == memberId)
                .SumAsync(pr => pr.PointsEarned);
        }
    }
}
